﻿using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Diagnostics;
using System.Reflection;
using ASPItalia.ModelVirtualCasting.Common;
using ASPItalia.ModelVirtualCasting.Parts;

namespace ASPItalia.ModelVirtualCasting
{
    internal class MefRepositoryFactory : IRepositoryFactory
    {
        private const string TRACE_INFO = "WARNING: the repository '{0}' is a fake object.\n";

        private CompositionContainer _container;

        public MefRepositoryFactory()
        {
            this.Initialize();
        }

        private void Initialize()
        {
            // Load the assembly containing the parts to be imported
            var assembly = Assembly.Load(Configuration.RepositoryAssemblyName);

            // Generate the catalog
            var catalog = new AssemblyCatalog(assembly);

            // Generate the composition container
            _container = new CompositionContainer(catalog);
        }

        public RepositoryFactoryType FactoryType
        {
            get { return RepositoryFactoryType.Mef; }
        }

        public object Container
        {
            get { return _container; }
        }

        private T CreateRepository<T, P>()
            where P : IRepositoryPart<T>, new()
        {
            // Create the part related to the repository and compose it
            P part = new P();
            _container.ComposeParts(part);

            // Using export metadata...
            if (part.Repository.Metadata.IsFake)
            {
                Debug.Write(string.Format(TRACE_INFO, part.Repository.Metadata.Name));
            }

            // Get the repository instance
            return part.Repository.Value;
        }

        public ICandidateRepository CreateCandidateRepository()
        {
            // Generate the new repository instance and return it
            return this.CreateRepository<ICandidateRepository, CandidateRepositoryPart>();
        }

        public ICountryRepository CreateCountryRepository()
        {
            // Generate the new repository instance and return it
            return this.CreateRepository<ICountryRepository, CountryRepositoryPart>();
        }

        public IJobLevelRepository CreateJobLevelRepository()
        {
            // Generate the new repository instance and return it
            return this.CreateRepository<IJobLevelRepository, JobLevelRepositoryPart>();
        }

        public IJobTypeRepository CreateJobTypeRepository()
        {
            // Generate the new repository instance and return it
            return this.CreateRepository<IJobTypeRepository, JobTypeRepositoryPart>();
        }

        public ILanguageRepository CreateLanguageRepository()
        {
            // Generate the new repository instance and return it
            return this.CreateRepository<ILanguageRepository, LanguageRepositoryPart>();
        }

        public IModelRepository CreateModelRepository()
        {
            // Generate the new repository instance and return it
            return this.CreateRepository<IModelRepository, ModelRepositoryPart>();
        }

        public INewsRepository CreateNewsRepository()
        {
            // Generate the new repository instance and return it
            return this.CreateRepository<INewsRepository, NewsRepositoryPart>();
        }

        public IPersonRepository CreatePersonRepository()
        {
            // Generate the new repository instance and return it
            return this.CreateRepository<IPersonRepository, PersonRepositoryPart>();
        }

        public IRequestRepository CreateRequestRepository()
        {
            // Generate the new repository instance and return it
            return this.CreateRepository<IRequestRepository, RequestRepositoryPart>();
        }

        public IUserRepository CreateUserRepository()
        {
            // Generate the new repository instance and return it
            return this.CreateRepository<IUserRepository, UserRepositoryPart>();
        }

        public IUserRoleRepository CreateUserRoleRepository()
        {
            // Generate the new repository instance and return it
            return this.CreateRepository<IUserRoleRepository, UserRoleRepositoryPart>();
        }
    }
}
